home *** CD-ROM | disk | FTP | other *** search
- /* $Id: ddsample.c,v 3.1 1998/06/02 01:33:51 brianp Exp $ */
-
- /*
- * Mesa 3-D graphics library
- * Version: 3.0
- * Copyright (C) 1995-1998 Brian Paul
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
- /*
- * $Log: ddsample.c,v $
- * Revision 3.1 1998/06/02 01:33:51 brianp
- * updated for v3.0 device driver changes
- *
- * Revision 3.0 1998/01/31 20:50:03 brianp
- * initial rev
- *
- */
-
-
-
- /*
- * This is a sample template for writing new Mesa device drivers.
- * You'll have to rewrite much of the code below.
- *
- * Let's say you're interfacing Mesa to a window/operating system
- * called FOO. Replace all occurances of FOOMesa with the real name
- * you select for your interface (i.e. XMesa, WMesa, AmigaMesa).
- *
- * You'll have to design an API for clients to use, defined in a
- * header called Mesa/include/GL/FooMesa.h Use the sample as an
- * example. The API should at least have functions for creating
- * rendering contexts, binding rendering contexts to windows/frame
- * buffers, etc.
- *
- * Next, you'll have to write implementations for the device driver
- * functions described in dd.h
- *
- * Note that you'll usually have to flip Y coordinates since Mesa's
- * window coordinates start at the bottom and increase upward. Most
- * window system's Y-axis increases downward
- *
- * Functions marked OPTIONAL may be completely omitted by your driver.
- *
- * Your Makefile should compile this module along with the rest of
- * the core Mesa library.
- */
-
-
- #include <stdlib.h>
- #include "GL/FooMesa.h"
- #include "context.h"
- #include "matrix.h"
- #include "types.h"
- #include "vb.h"
-
-
-
- /*
- * In C++ terms, this class derives from the GLvisual class.
- * Add system-specific fields to it.
- */
- struct foo_mesa_visual {
- GLvisual *gl_visual;
- GLboolean db_flag; /* double buffered? */
- GLboolean rgb_flag; /* RGB mode? */
- GLuint depth; /* bits per pixel (1, 8, 24, etc) */
- };
-
-
- /*
- * In C++ terms, this class derives from the GLframebuffer class.
- * Add system-specific fields to it.
- */
- struct foo_mesa_buffer {
- GLframebuffer *gl_buffer; /* The depth, stencil, accum, etc buffers */
- void *the_window; /* your window handle, etc */
- int Width, Height;
- };
-
-
-
- /*
- * In C++ terms, this class derives from the GLcontext class.
- * Add system-specific fields to it.
- */
- struct foo_mesa_context {
- GLcontext *gl_ctx; /* the core library context */
- FooMesaVisual visual;
- FooMesaBuffer Buffer;
- GLuint ClearIndex;
- GLubyte ClearColor[4];
- GLuint CurrentIndex;
- GLubyte CurrentColor[4];
- /* etc... */
- };
-
-
- static FooMesaContext CurrentContext = 0;
- static FooMesaBuffer CurrentBuffer = 0;
-
-
-
- static void setup_DD_pointers( GLcontext *ctx );
-
-
- /**********************************************************************/
- /***** Miscellaneous device driver funcs *****/
- /**********************************************************************/
-
-
- static void finish( GLcontext *ctx )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- /* OPTIONAL FUNCTION: implements glFinish if possible */
- }
-
-
-
- static void flush( GLcontext *ctx )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- /* OPTIONAL FUNCTION: implements glFlush if possible */
- }
-
-
-
- static void clear_index( GLcontext *ctx, GLuint index )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- foo->ClearIndex = index;
- }
-
-
-
- static void clear_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- foo->ClearColor[0] = r;
- foo->ClearColor[1] = g;
- foo->ClearColor[2] = b;
- foo->ClearColor[3] = a;
- }
-
-
-
- static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
- GLint x, GLint y, GLint width, GLint height )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- /*
- * Clear the specified region of the buffers indicated by 'mask'
- * using the clear color or index as specified by one of the two
- * functions above.
- * If all==GL_TRUE, clear whole buffer, else just clear region defined
- * by x,y,width,height
- */
-
- return mask; /* return mask of buffers remaining to be cleared */
- }
-
-
-
- static void set_index( GLcontext *ctx, GLuint index )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- foo->CurrentIndex = index;
- }
-
-
-
- static void set_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- foo->CurrentColor[0] = r;
- foo->CurrentColor[1] = g;
- foo->CurrentColor[2] = b;
- foo->CurrentColor[3] = a;
- }
-
-
-
- /*
- * OPTIONAL FUNCTION: implement glIndexMask if possible, else
- * return GL_FALSE
- */
- static GLboolean index_mask( GLcontext *ctx, GLuint mask )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- return GL_FALSE;
- }
-
-
-
- /*
- * OPTIONAL FUNCTION: implement glColorMask if possible, else
- * return GL_FALSE
- */
- static GLboolean color_mask( GLcontext *ctx,
- GLboolean rmask, GLboolean gmask,
- GLboolean bmask, GLboolean amask)
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- return GL_FALSE;
- }
-
-
-
- /*
- * OPTIONAL FUNCTION:
- * Implements glLogicOp if possible. Return GL_TRUE if the device driver
- * can perform the operation, otherwise return GL_FALSE. If GL_FALSE
- * is returned, the logic op will be done in software by Mesa.
- */
- static GLboolean logicop( GLcontext *ctx, GLenum op )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- return GL_FALSE;
- }
-
-
-
- /*
- * OPTIONAL FUNCTION: enable/disable dithering if applicable
- */
- static void dither( GLcontext *ctx, GLboolean enable )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- }
-
-
-
- /*
- * Set the current drawing/reading buffer, return GL_TRUE or GL_FALSE
- * for success/failure.
- */
- static GLboolean set_buffer( GLcontext *ctx, GLenum mode )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- setup_DD_pointers( ctx );
- return GL_TRUE;
- }
-
-
-
- /*
- * Return the width and height of the current buffer.
- * If anything special has to been done when the buffer/window is
- * resized, do it now.
- */
- static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
-
- *width = foo->Buffer->Width = 12345; /* XXX fix these */
- *height = foo->Buffer->Height = 12345;
-
- }
-
-
-
- /**********************************************************************/
- /***** Dummy functions *****/
- /**********************************************************************/
-
- static void WriteCIPixel( GLint x, GLint y, GLuint index )
- {
- }
-
- static void WriteRGBAPixel( GLint x, GLint y, const GLubyte color[4] )
- {
- }
-
- static void WriteRGBPixel( GLint x, GLint y, const GLubyte color[3] )
- {
- }
-
- static GLuint ReadCIPixel( GLint x, GLint y )
- {
- return 0;
- }
-
- static void ReadRGBAPixel( GLint x, GLint y, GLubyte color[4] )
- {
- }
-
- #define FLIP(y) foo->Buffer->Height - (y) - 1;
-
-
- /**********************************************************************/
- /***** Accelerated point, line, triangle rendering *****/
- /**********************************************************************/
-
-
- /* There may several functions like this, for different screen modes, etc */
- static void fast_points_function( GLcontext *ctx, GLuint first, GLuint last )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- struct vertex_buffer *VB = ctx->VB;
- GLint i;
-
- /* Render a number of points by some hardware/OS accerated method */
- if (VB->MonoColor) {
- /* draw all points using the current color (set_color) */
- for (i=first;i<=last;i++) {
- if (VB->ClipMask[i]==0) {
- /* compute window coordinate */
- int x, y;
- x = (GLint) VB->Win[i][0];
- y = FLIP( (GLint) VB->Win[i][1] );
- WriteRGBAPixel(x, y, foo->CurrentColor);
- }
- }
- }
- else {
- /* each point is a different color */
- for (i=first;i<=last;i++) {
- if (VB->ClipMask[i]==0) {
- int x, y;
- x = (GLint) VB->Win[i][0];
- y = FLIP( (GLint) VB->Win[i][1] );
- WriteRGBAPixel(x, y, foo->CurrentColor);
- }
- }
- }
- }
-
-
-
-
- /* There may several functions like this, for different screen modes, etc */
- static void fast_line_function( GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv )
- {
- /* Render a line by some hardware/OS accerated method */
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- struct vertex_buffer *VB = ctx->VB;
- int x0, y0, x1, y1;
- GLubyte *pixel;
-
- if (VB->MonoColor) {
- pixel = foo->CurrentColor;
- }
- else {
- pixel = VB->Color[pv];
- }
-
- x0 = (int) VB->Win[v0][0];
- y0 = FLIP( (int) VB->Win[v0][1] );
- x1 = (int) VB->Win[v1][0];
- y1 = FLIP( (int) VB->Win[v1][1] );
-
- /* Draw line from (x0,y0) to (x1,y1) with current pixel color/index */
- }
-
-
-
-
- /* There may several functions like this, for different screen modes, etc */
- static void fast_triangle_function( GLcontext *ctx, GLuint v0,
- GLuint v1, GLuint v2, GLuint pv )
- {
- /* Render a triangle by some hardware/OS accerated method */
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- struct vertex_buffer *VB = ctx->VB;
- GLubyte *pixel;
-
- if (VB->MonoColor) {
- pixel = foo->CurrentColor;
- }
- else {
- pixel = VB->Color[pv];
- }
-
- /* Draw triangle with current pixel color/index */
- }
-
-
-
- /**********************************************************************/
- /***** Write spans of pixels *****/
- /**********************************************************************/
-
-
- static void write_index8_span( const GLcontext *ctx,
- GLuint n, GLint x, GLint y,
- const GLubyte index[],
- const GLubyte mask[] )
- {
- GLint i;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- WriteCIPixel(x+i, y, index[i]);
- }
- }
- }
-
-
- static void write_index32_span( const GLcontext *ctx,
- GLuint n, GLint x, GLint y,
- const GLuint index[],
- const GLubyte mask[] )
- {
- GLint i;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- WriteCIPixel(x+i, y, index[i]);
- }
- }
- }
-
-
-
- static void write_mono_index_span( const GLcontext *ctx,
- GLuint n, GLint x, GLint y,
- const GLubyte mask[] )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- GLuint i;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- WriteCIPixel(x+i, y, foo->CurrentIndex);
- }
- }
- }
-
-
-
- static void write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
- const GLubyte rgba[][4], const GLubyte mask[] )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- GLuint i;
- y = FLIP(y);
- if (mask) {
- /* draw some pixels */
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteRGBAPixel( x+i, y, foo->CurrentColor );
- }
- }
- }
- else {
- /* draw all pixels */
- for (i=0; i<n; i++) {
- WriteRGBAPixel( x+i, y, foo->CurrentColor );
- }
- }
- }
-
-
- static void write_rgb_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
- const GLubyte rgb[][3], const GLubyte mask[] )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- GLuint i;
- y = FLIP(y);
- if (mask) {
- /* draw some pixels */
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteRGBPixel( x+i, y, rgb[i] );
- }
- }
- }
- else {
- /* draw all pixels */
- for (i=0; i<n; i++) {
- WriteRGBPixel( x+i, y, rgb[i] );
- }
- }
- }
-
-
-
- static void write_mono_rgba_span( const GLcontext *ctx,
- GLuint n, GLint x, GLint y,
- const GLubyte mask[])
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- GLint i;
- y = FLIP(y);
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteRGBAPixel( x+i, y, foo->CurrentColor );
- }
- }
- }
-
-
-
- /**********************************************************************/
- /***** Read spans of pixels *****/
- /**********************************************************************/
-
-
- static void read_index_span( const GLcontext *ctx,
- GLuint n, GLint x, GLint y, GLuint index[])
- {
- GLint i;
- for (i=0; i<n; i++) {
- index[i] = ReadCIPixel( x+i, y );
- }
- }
-
-
-
- static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
- GLubyte rgba[][4] )
- {
- int i;
- for (i=0; i<n; i++) {
- ReadRGBAPixel( x+i, y, rgba[i] );
- }
- }
-
-
-
- /**********************************************************************/
- /***** Write arrays of pixels *****/
- /**********************************************************************/
-
-
- static void write_index_pixels( const GLcontext *ctx,
- GLuint n, const GLint x[], const GLint y[],
- const GLuint index[], const GLubyte mask[] )
- {
- GLint i;
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteCIPixel( x[i], y[i], index[i] );
- }
- }
- }
-
-
-
- static void write_mono_index_pixels( const GLcontext *ctx,
- GLuint n,
- const GLint x[], const GLint y[],
- const GLubyte mask[] )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- GLint i;
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteCIPixel( x[i], y[i], foo->CurrentIndex );
- }
- }
- }
-
-
-
- static void write_rgba_pixels( const GLcontext *ctx,
- GLuint n, const GLint x[], const GLint y[],
- const GLubyte rgba[][4], const GLubyte mask[] )
- {
- GLint i;
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteRGBAPixel( x[i], y[i], rgba[i] );
- }
- }
- }
-
-
-
- static void write_mono_rgba_pixels( const GLcontext *ctx,
- GLuint n, const GLint x[], const GLint y[],
- const GLubyte mask[] )
- {
- struct foo_mesa_context *foo = (struct foo_mesa_context *) ctx->DriverCtx;
- GLint i;
- for (i=0; i<n; i++) {
- if (mask[i]) {
- WriteRGBAPixel( x[i], y[i], foo->CurrentColor );
- }
- }
- }
-
-
-
-
- /**********************************************************************/
- /***** Read arrays of pixels *****/
- /**********************************************************************/
-
- /* Read an array of color index pixels. */
- static void read_index_pixels( const GLcontext *ctx,
- GLuint n, const GLint x[], const GLint y[],
- GLuint index[], const GLubyte mask[] )
- {
- GLint i;
- for (i=0; i<n; i++) {
- if (mask[i]) {
- index[i] = ReadCIPixel( x[i], y[i] );
- }
- }
- }
-
-
-
- static void read_rgba_pixels( const GLcontext *ctx,
- GLuint n, const GLint x[], const GLint y[],
- GLubyte rgba[][4], const GLubyte mask[] )
- {
- GLint i;
- for (i=0; i<n; i++) {
- if (mask[i]) {
- ReadRGBAPixel( x[i], y[i], rgba[i] );
- }
- }
- }
-
-
-
-
- /**********************************************************************/
- /**********************************************************************/
-
-
- static void setup_DD_pointers( GLcontext *ctx )
- {
- /* Initialize all the pointers in the DD struct. Do this whenever */
- /* a new context is made current or we change buffers via set_buffer! */
-
- ctx->Driver.UpdateState = setup_DD_pointers;
-
- ctx->Driver.ClearIndex = clear_index;
- ctx->Driver.ClearColor = clear_color;
- ctx->Driver.Clear = clear;
-
- ctx->Driver.Index = set_index;
- ctx->Driver.Color = set_color;
-
- ctx->Driver.SetBuffer = set_buffer;
- ctx->Driver.GetBufferSize = get_buffer_size;
-
- ctx->Driver.PointsFunc = fast_points_function;
- ctx->Driver.LineFunc = fast_line_function;
- ctx->Driver.TriangleFunc = fast_triangle_function;
-
- /* Pixel/span writing functions: */
- ctx->Driver.WriteRGBASpan = write_rgba_span;
- ctx->Driver.WriteRGBSpan = write_rgb_span;
- ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span;
- ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
- ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels;
-
- ctx->Driver.WriteCI32Span = write_index32_span;
- ctx->Driver.WriteCI8Span = write_index8_span;
- ctx->Driver.WriteMonoCISpan = write_mono_index_span;
- ctx->Driver.WriteCI32Pixels = write_index_pixels;
- ctx->Driver.WriteMonoCIPixels = write_mono_index_pixels;
-
- /* Pixel/span reading functions: */
- ctx->Driver.ReadCI32Span = read_index_span;
- ctx->Driver.ReadRGBASpan = read_rgba_span;
- ctx->Driver.ReadCI32Pixels = read_index_pixels;
- ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
-
-
- /*
- * OPTIONAL FUNCTIONS: these may be left uninitialized if the device
- * driver can't/needn't implement them.
- */
- ctx->Driver.Finish = finish;
- ctx->Driver.Flush = flush;
- ctx->Driver.IndexMask = index_mask;
- ctx->Driver.ColorMask = color_mask;
- ctx->Driver.LogicOp = logicop;
- ctx->Driver.Dither = dither;
- }
-
-
-
- /**********************************************************************/
- /***** FOO/Mesa Public API Functions *****/
- /**********************************************************************/
-
-
-
- /*
- * The exact arguments to this function will depend on your window system
- */
- FooMesaVisual FooMesaCreateVisual( GLboolean rgb_mode, GLboolean dbFlag,
- GLint depthSize, GLint stencilSize,
- GLint accumSize )
- {
- FooMesaVisual v;
- GLint redBits, greenBits, blueBits, alphaBits, indexBits;
- GLboolean alphaFlag = GL_FALSE;
-
- v = (FooMesaVisual) calloc( 1, sizeof(struct foo_mesa_visual) );
- if (!v) {
- return NULL;
- }
-
- if (rgb_mode) {
- /* RGB(A) mode */
- redBits = 8; /* XXX 8 is just an example */
- greenBits = 8;
- blueBits = 8;
- alphaBits = 8;
- indexBits = 0;
- }
- else {
- /* color index mode */
- redBits = 0;
- greenBits = 0;
- blueBits = 0;
- alphaBits = 0;
- indexBits = 8; /* XXX 8 is just an example */
- }
-
- /* Create core visual */
- v->gl_visual = gl_create_visual( rgb_mode,
- alphaFlag,
- dbFlag,
- GL_FALSE, /* stereo */
- depthSize,
- stencilSize,
- accumSize,
- indexBits,
- redBits, greenBits, blueBits, alphaBits );
-
- return v;
- }
-
-
-
- void FooMesaDestroyVisual( FooMesaVisual v )
- {
- gl_destroy_visual( v->gl_visual );
- free( v );
- }
-
-
-
-
- FooMesaBuffer FooMesaCreateBuffer( FooMesaVisual visual,
- void *your_window_id )
- {
- FooMesaBuffer b;
-
- b = (FooMesaBuffer) calloc( 1, sizeof(struct foo_mesa_buffer) );
- if (!b) {
- return NULL;
- }
-
- b->gl_buffer = gl_create_framebuffer( visual->gl_visual );
- b->the_window = your_window_id;
-
- /* other stuff */
-
- return b;
- }
-
-
-
- void FooMesaDestroyBuffer( FooMesaBuffer b )
- {
- gl_destroy_framebuffer( b->gl_buffer );
- free( b );
- }
-
-
-
-
- FooMesaContext FooMesaCreateContext( FooMesaVisual visual,
- FooMesaContext share )
- {
- FooMesaContext c;
- GLboolean direct = GL_FALSE;
-
- c = (FooMesaContext) calloc( 1, sizeof(struct foo_mesa_context) );
- if (!c) {
- return NULL;
- }
-
- c->gl_ctx = gl_create_context( visual->gl_visual,
- share ? share->gl_ctx : NULL,
- (void *) c, direct );
-
-
- /* you probably have to do a bunch of other initializations here. */
-
- return c;
- }
-
-
-
- void FooMesaDestroyContext( FooMesaContext c )
- {
- gl_destroy_context( c->gl_ctx );
- free( c );
- }
-
-
-
- /*
- * Make the specified context and buffer the current one.
- */
- void FooMesaMakeCurrent( FooMesaContext c, FooMesaBuffer b )
- {
- if (c && b) {
- gl_make_current( c->gl_ctx, b->gl_buffer );
- CurrentContext = c;
- CurrentBuffer = b;
- if (c->gl_ctx->Viewport.Width==0) {
- /* initialize viewport to window size */
- gl_Viewport( c->gl_ctx, 0, 0, c->Buffer->Width, c->Buffer->Height );
- }
- }
- else {
- /* Detach */
- gl_make_current( NULL, NULL );
- CurrentContext = 0;
- CurrentBuffer = 0;
- }
- }
-
-
-
- void FooMesaSwapBuffers( FooMesaBuffer b )
- {
- /* copy/swap back buffer to front if applicable */
- }
-
-
-
- /* you may need to add other FOO/Mesa functions too... */
-
-